package cn.com.support.context;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.util.RequestMatcher;

import cn.com.commons.utils.StringUtil;
import cn.com.dal.dataobject.sys.MenuDO;
import static cn.com.support.authentication.ResourceAuthCode.*;
import cn.com.support.authentication.AuteniticationException;
import cn.com.support.authentication.AuthenticationUtil;
import cn.com.support.authentication.ResourceAuthCode;

/**
 * 权限上下文，
 * 
 * @since 2012-3-14 下午11:37:57
 * @version 1.0
 * @author Microbun
 * 
 */
public class AuthenticationContext {


	private static Logger logger = LoggerFactory
			.getLogger(AuthenticationContext.class);

	private static Map<String, ConcurrentSkipListSet<ConfigAttribute>> AUTH_MAP = new ConcurrentHashMap<String, ConcurrentSkipListSet<ConfigAttribute>>();


	/**
	 * 根据资源获取只读权限码集
	 * 
	 * @param resource
	 * @return 权限码只读集合
	 */
	public static Collection<ConfigAttribute> getAuthentication(String resource) {
		Collection<ConfigAttribute> attributes = AUTH_MAP.get(TYPE_MENU+":"+resource);
		if (attributes == null) {
			attributes = new HashSet<ConfigAttribute>();
		}
		// attributes.add(new ResourceAuthCode("1"));
		return attributes;
	}

	/**
	 * 获取所有的只读权限码集
	 * 
	 * @return 所有权限码只读集合
	 */
	public static Collection<ConfigAttribute> getAllAuthentication() {
		Collection<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
		for (Entry<String, ConcurrentSkipListSet<ConfigAttribute>> entry : AUTH_MAP
				.entrySet()) {
			allAttributes.addAll(entry.getValue());
		}
		// allAttributes.add(new ResourceAuthCode("1"));
		return Collections.unmodifiableCollection(allAttributes);
	}

	/**
	 * 重置所有菜单验证，支持并发，同时保证是数据的完整性
	 * 
	 * @param menus
	 */
	public static void resetMenus(List<MenuDO> menus) {
		logger.debug("{}:重置菜单AuthenticationContext", Thread.currentThread()
				.getName());
		Set<String> keySet = AUTH_MAP.keySet();
		// 如果context不是在CLEAING中，，置为RESETING_MENUS状态，并执行resetMenus操作，然后将状态置为AVAILABLE
		for (String key : keySet) {
			if (key.matches(TYPE_MENU + ".*")) {
				AUTH_MAP.remove(key);
			}
		}
		appedMenus(menus);
		logger.debug("{}:完成重置菜单AuthenticationContext", Thread.currentThread()
				.getName());
	}

	/**
	 * 追加菜单到验证上下文，支持并发追加
	 * 
	 * @param menus
	 */
	public static void appedMenus(List<MenuDO> menus) {
		logger.debug("{}:追加菜单AuthenticationContext", Thread.currentThread()
				.getName());
		String resource = null;
		for (MenuDO menu : menus) {
			resource = TYPE_MENU + ":" + menu.getUrlPath();
			if (!StringUtil.isEmpty(resource)) {
				ResourceAuthCode code = null;
				code = AuthenticationUtil.createAuthCode(menu.getId(),
						ResourceAuthCode.TYPE_MENU);
				code.setType(TYPE_MENU);
				if (AUTH_MAP.containsKey(resource)) {
					Set<ConfigAttribute> codeSet = AUTH_MAP.get(resource);
					codeSet.add(code);
				} else {
					ConcurrentSkipListSet<ConfigAttribute> codeSet = new ConcurrentSkipListSet<ConfigAttribute>();
					codeSet.add(code);
					AUTH_MAP.put(resource, codeSet);
				}

			}
		}
		logger.debug("{}:完成追加菜单AuthenticationContext", Thread.currentThread()
				.getName());
	}

	/**
	 * 清空权限上下文
	 */
	public static void clear() {
		logger.debug("{}:正在清空AuthenticationContext", Thread.currentThread()
				.getName());
		AUTH_MAP.clear();
		logger.debug("{}:已经清空AuthenticationContext", Thread.currentThread()
				.getName());
	}

}
